use std::sync::Arc;

use axum::Router;
use dotenv::dotenv;
use short_url::{admin_api, auth_api, config, web_api, AppState};
use sqlx::postgres::PgPoolOptions;
use tower_http::cors::{Any, CorsLayer};

#[tokio::main]
async fn main() {
    dotenv().ok();
    tracing_subscriber::fmt::init();

    let cfg = config::Config::from_env()
        .map_err(|err| tracing::error!("初始化配置失败：{err}"))
        .unwrap();
    let web_addr = cfg.web.addr.clone();

    let pool = PgPoolOptions::new()
        .max_connections(cfg.db.max_conns)
        .connect(&cfg.db.dsn)
        .await
        .map_err(|err| tracing::error!("数据库连接失败：{err}"))
        .unwrap();

    /*
    let rds_man = bb8_redis::RedisConnectionManager::new(cfg.cache.dsn.as_str())
        .map_err(|err| tracing::error!("redis连接失败：{err}"))
        .unwrap();
    let rds_pool = bb8::Pool::builder()
        .max_size(cfg.cache.max_conns)
        .build(rds_man)
        .await
        .map_err(|err| tracing::error!("redis连接池创建失败：{err}"))
        .unwrap();
     */

    let state = Arc::new(AppState {
        cfg: Arc::new(cfg),
        pool: Arc::new(pool),
        // rds_pool: Arc::new(rds_pool),
    });

    let tcp_listener = tokio::net::TcpListener::bind(&web_addr)
        .await
        .map_err(|err| tracing::error!("TCP监听失败：{err}"))
        .unwrap();
    tracing::info!("服务监听于：{}", &web_addr);

    let app = Router::new()
        .nest("/visit", web_api::visit_router(state.clone()))
        .nest("/auth", auth_api::route(state.clone()))
        .nest("/", web_api::init_router(state.clone()))
        .nest("/", admin_api::init_router(state.clone()))
        .layer(
            CorsLayer::new()
                .allow_headers(Any)
                .allow_methods(Any)
                .allow_origin(Any),
        );
    axum::serve(tcp_listener, app)
        .await
        .map_err(|err| tracing::error!("AXUM服务开启失败：{err}"))
        .unwrap();
}
